#include "textreport.h"

#include "textreport_p.h"

#include <qprintpreviewdialog.h>
#include <QTextDocument>
#include <QAbstractTextDocumentLayout>
#include <QPrinter>
#include <QPainter>
#include <QTextFrame>
#include <QFileInfo>
#include <QFile>
#include <QFileDialog>

namespace YReport {
TextReport::TextReport(QObject *parent)  :
    Report(parent),
    p(new TextReportPrivate())
{

}

TextReport::~TextReport()
{
    delete p;
}

void TextReport::exportPdf(const QTextDocument *document, const QString &caption, const QString &filename)
{
    if (!document) return;

    // file save dialog
    QString dialogcaption = caption.isEmpty() ? "Export PDF" : caption;
    QString exportname;
    if (QFile::exists(filename)) {
        exportname = filename;
    } else {
        exportname = QFileDialog::getSaveFileName(this->parent(), dialogcaption,
                                                  filename, "*.pdf");
    }

    if (exportname.isEmpty()) return;
    if (QFileInfo(exportname).suffix().isEmpty())
        exportname.append(".pdf");

    // setup printer
    printer()->setOutputFormat(QPrinter::PdfFormat);
    printer()->setOutputFileName(exportname);

    // print it
    p->document_ = document->clone();
    print(printer());

    delete p->document_;
    p->document_ = 0;
}

void TextReport::preview(const QTextDocument *document, const QString &title)
{
    if (!document) return;

    QPrintPreviewDialog dialog(printer(), parent());
    dialog.setWindowTitle(title.isEmpty() ? "预览" : title);
    connect(&dialog, &QPrintPreviewDialog::paintRequested, this, &TextReport::print);
    p->document_ = document->clone();
    dialog.showMaximized();
    dialog.exec();

    delete p->document_;
    p->document_ = 0;
}

void TextReport::print(QPrinter *printer)
{
    if (!printer || !p->document_) return;

    p->document_->setUseDesignMetrics(true);
    p->document_->documentLayout()->setPaintDevice(printer);

    QRectF rect = this->printer()->paperRect();

    rect.adjust(millimeterToInches(15) * printer->logicalDpiX(),
                millimeterToInches(15) * printer->logicalDpiY(),
                -millimeterToInches(15) * printer->logicalDpiX(),
                -millimeterToInches(15) * printer->logicalDpiY());
    p->document_->setPageSize(rect.size());
    // dump existing margin (if any)
    QTextFrameFormat fmt = p->document_->rootFrame()->frameFormat();
    fmt.setMargin(0);
    p->document_->rootFrame()->setFrameFormat(fmt);

    // to iterate through pages we have to worry about
    // copies, collation, page range, and print order

    // get num copies
    int doccopies;
    int pagecopies;
    if (printer->collateCopies()) {
        doccopies = 1;
        pagecopies = printer->numCopies();
    } else {
        doccopies = printer->numCopies();
        pagecopies = 1;
    }

    // get page range
    int firstpage = printer->fromPage();
    int lastpage = printer->toPage();
    if (firstpage == 0 && lastpage == 0) { // all pages
        firstpage = 1;
        lastpage = p->document_->pageCount();
    }

    // print order
    bool ascending = true;
    if (printer->pageOrder() == QPrinter::LastPageFirst) {
        int tmp = firstpage;
        firstpage = lastpage;
        lastpage = tmp;
        ascending = false;
    }

    // loop through and print pages
    QPainter painter(printer);
    painter.setRenderHints(QPainter::Antialiasing |
                           QPainter::TextAntialiasing |
                           QPainter::SmoothPixmapTransform, true);
    for (int dc=0; dc<doccopies; dc++) {
        int pagenum = firstpage;
        while (true) {
            for (int pc=0; pc<pagecopies; pc++) {
                if (printer->printerState() == QPrinter::Aborted ||
                    printer->printerState() == QPrinter::Error) {
                    return;
                }
                // print page
                paintPage(&painter, p->document_, pagenum);
                if (pc < pagecopies-1) printer->newPage();
            }
            if (pagenum == lastpage) break;
            if (ascending) pagenum++;
            else           pagenum--;
            printer->newPage();
        }

        if (dc < doccopies-1) printer->newPage();
    }
}


void TextReport::paintPage(QPainter *painter, QTextDocument *document, int pagenum)
{
//    QRectF rect;
    double onepoint = painter->device()->logicalDpiY() / 72.0;

//    // header
//    if (headersize_ > 0) {
//        rect = headerRect(painter->device());
//        if (headerrule_ > 0.0) {
//            painter->save();
//            // allow space between rule and header
//            painter->translate(0, onepoint + (headerrule_ * onepoint / 2.0));
//            painter->setPen(QPen(Qt::black, headerrule_ * onepoint));
//            painter->drawLine(rect.bottomLeft(), rect.bottomRight());
//            painter->restore();
//        }

//        // replace page variables
//        QString header = headertext_;
//        header.replace("&page;", QString::number(pagenum));
//        if (dateformat_.isEmpty()) {
//            header.replace("&date;", QDate::currentDate().toString());
//        } else {
//            header.replace("&date;", QDate::currentDate().toString(dateformat_));
//        }


//        painter->save();
//        painter->translate(rect.left(), rect.top());
//        QRectF clip(0, 0, rect.width(), rect.height());
//        QTextDocument doc;
//        doc.setUseDesignMetrics(true);
//        doc.setHtml(header);
//        doc.documentLayout()->setPaintDevice(painter->device());
//        doc.setPageSize(rect.size());

//        // align text to bottom
//        double newtop = clip.bottom() - doc.size().height();
//        clip.setHeight(doc.size().height());
//        painter->translate(0, newtop);

//        doc.drawContents(painter, clip);
//        painter->restore();
//    }

//    // footer
//    if (footersize_ > 0) {
//        rect = footerRect(painter->device());
//        if (footerrule_ > 0.0) {
//            painter->save();
//            // allow space between rule and footer
//            painter->translate(0, -onepoint + (-footerrule_ * onepoint / 2.0));
//            painter->setPen(QPen(Qt::black, footerrule_ * onepoint));
//            painter->drawLine(rect.topLeft(), rect.topRight());
//            painter->restore();
//        }

//        // replace page variables
//        QString footer = footertext_;
//        footer.replace("&page;", QString::number(pagenum));
//        if (dateformat_.isEmpty()) {
//            footer.replace("&date;", QDate::currentDate().toString());
//        } else {
//            footer.replace("&date;", QDate::currentDate().toString(dateformat_));
//        }

//        painter->save();
//        painter->translate(rect.left(), rect.top());
//        QRectF clip(0, 0, rect.width(), rect.height());
//        QTextDocument doc;
//        doc.setUseDesignMetrics(true);
//        doc.setHtml(footer);
//        doc.documentLayout()->setPaintDevice(painter->device());
//        doc.setPageSize(rect.size());
//        doc.drawContents(painter, clip);
//        painter->restore();
//    }

    // content
    painter->save();

//    rect = contentRect(painter->device());

            QPaintDevice *device = painter->device();
    QRectF rect = this->printer()->paperRect();
        // adjust for DPI
        rect.setWidth(rect.width() *
                      device->logicalDpiX() / this->printer()->logicalDpiX());
        rect.setHeight(rect.height() *
                      device->logicalDpiY() / this->printer()->logicalDpiY());

    rect.adjust(millimeterToInches(15) * this->printer()->logicalDpiX(),
                millimeterToInches(15) * this->printer()->logicalDpiY(),
                -millimeterToInches(15) * this->printer()->logicalDpiX(),
                -millimeterToInches(15) * this->printer()->logicalDpiY());
    painter->translate(rect.left(), rect.top() - (pagenum-1) * rect.height());
    QRectF clip(0, (pagenum-1) * rect.height(), rect.width(), rect.height());

    document->drawContents(painter, clip);

    painter->restore();

}


} //namespace YReport
